
package com.guiji.text2video.fastvideo.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.guiji.text2video.common.core.web.controller.BaseController;
import com.guiji.text2video.common.core.web.domain.AjaxResult;
import com.guiji.text2video.common.redis.service.RedisService;
import com.guiji.text2video.fastvideo.domain.vo.Text2videoComposeTask;
import com.guiji.text2video.fastvideo.domain.vo.Text2videoJob;
import com.guiji.text2video.fastvideo.domain.vo.Text2videoNlpTask;
import com.guiji.text2video.fastvideo.service.*;
import com.guiji.text2video.fastvideo.task.CommitNewsTimingTask;
import com.guiji.text2video.fastvideo.utils.Enums;
import com.guiji.text2video.fastvideo.utils.GeneratID;
import com.guiji.text2video.fastvideo.utils.GetLocalIpUtil;
import com.guiji.text2video.fastvideo.utils.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;


/**
 * @program: ruoyi
 * @description: 文本转视频controller
 * @author: gaoX
 * @create: 2021-04-09 14:50
 **/
@RefreshScope
@RestController
@RequestMapping("/job-v2")
public class JobController extends BaseController {

    private Logger logger = LoggerFactory.getLogger(JobController.class);

    @Autowired
    private INLPService NLPService;

    @Autowired
    IText2videoZipJobService iText2videoZipJobService;

    @Autowired
    IText2videoPoolsStatService iText2videoPoolsStatService;

    @Resource
    private CommitNewsTimingTask commitNewsTimingTask;
    @Resource
    private RedisService redisService;

    @Autowired
    private IText2videoJobService text2videoJobService;
    @Autowired
    private IText2videoNlpTaskService nlp;
    @Autowired
    private IText2videoComposeTaskService compose;

    @Value("${file-cache.wav-dir}")
    private String wavDir;

    @Value("${file-cache.task-video-dir}")
    private String taskVideoPath;

    @Value("${file-cache.task-video-url}")
    private String taskVideoUrl;

    /**
     * 提交任务，返回jobid
     */

    @PostMapping("/commit")
    //@PreAuthorize(hasAnyPermi = "@ss.hasRole('user')")
    public AjaxResult commit(@RequestBody Text2videoJob text2videoJob) throws InterruptedException {
        Map<String, Object> response = CollUtil.newHashMap();
        if (StrUtil.hasBlank(text2videoJob.getTitle(), text2videoJob.getContent())) {
            return AjaxResult.error(Enums.httpCode.ERROR_01.getValue());
        }
        if (text2videoJob.getContent().length() > Enums.numSign.contentSize.getKey()) {
            return AjaxResult.error(Enums.httpCode.ERROR_02.getValue());
        }
        //1,生成全局id
        String jobId = GeneratID.getJobGeneratID();
        text2videoJob.setJobId(jobId);
        text2videoJob.setCreateTime(new Date());
        text2videoJob.setIsSuccess(Enums.JobSign.RUNNING.getKey());
        //text2videoJob.setBackup1(GetLocalIpUtil.getIp());
        text2videoJobService.insertText2videoJob(text2videoJob);
        //2,更换不同版本NLP服务，异步任务-线程池
        NLPService.executeNLPAsync(text2videoJob);
        response.put("jobId", jobId);
        return AjaxResult.success(response);
    }

    /**
     * 提交新闻任务，返回jobid
     */

    @PostMapping("/commitNews")
    public AjaxResult commitNews(@RequestBody Text2videoJob text2videoJob) {

        logger.info("通过Controller接口提交任务:{}",JSONUtil.parseObj(text2videoJob).toString());
        commitNewsTimingTask.oneTypeNews(text2videoJob);
        return AjaxResult.success();
    }

    /**
     * 多任务接口
     *
     * @return
     */
    @PostMapping("/multiTask")
    public AjaxResult multiTasks(MultipartFile[] files, Text2videoJob job) {
        if (ObjectUtil.isNull(files) || files.length == Enums.numSign.zero.getKey()) {
            return AjaxResult.error(Enums.httpCode.ERROR_07.getValue());
        }

        if (files.length > Enums.numSign.batchSize.getKey()) {
            List<String> aList = new ArrayList<>();
            aList.add(Enums.httpCode.ERROR_08.getValue());
            return AjaxResult.success(aList);
        }

        List<String> list = new ArrayList<>();
        for (MultipartFile file : files) {
            list.add(GeneratID.getJobGeneratID());
        }
        List<File> fileList = iText2videoZipJobService.transferToLocal(files);
        new Thread(new Runnable() {
            @Override
            public void run() {
                //做校验
                iText2videoZipJobService.checkFormat(fileList, list, "", job);
            }
        }).start();

        return AjaxResult.success(list);
    }

    /**
     * zip刷新获取详情
     *
     * @param zipId
     * @return
     */
    @GetMapping("/multiTaskZipRefresh/{zipId}")
    public AjaxResult multiTaskZipRefresh(@PathVariable String zipId) {
        if (ObjectUtil.isNull(zipId)) {
            return AjaxResult.error(Enums.httpCode.ERROR_07.getValue());
        }
        Map<String, String> map;
        try {
            map = iText2videoZipJobService.updateStat(zipId);
        } catch (Exception e) {
            logger.error(Enums.httpCode.ERROR_18.getValue(), e);
            return AjaxResult.error(Enums.httpCode.ERROR_04.getValue());
        }
        return AjaxResult.success(map);
    }

    /**
     * zip包接口
     *
     * @param fileZip
     * @return
     */
    @PostMapping("/multiTaskZip")
    public AjaxResult multiTaskZips(MultipartFile fileZip, Text2videoJob job) {
        if (ObjectUtil.isNull(fileZip)) {
            return AjaxResult.error(Enums.httpCode.ERROR_07.getValue());
        }

        long size = fileZip.getSize();
        if (size > Enums.numSign.fileSize.getKey()) {
            return AjaxResult.error(Enums.httpCode.ERROR_09.getValue());
        }

        String zipId = null;
        Map map = new HashMap();
        try {
            zipId = iText2videoZipJobService.multiTaskZip(fileZip, job);
            map.put("zipId", zipId);
        } catch (Exception e) {
            logger.error(Enums.httpCode.ERROR_18.getValue(), e);
            return AjaxResult.error(Enums.httpCode.ERROR_04.getValue());
        }
        return AjaxResult.success(map);
    }


    @GetMapping("/progress/{jobId}")
    public AjaxResult progress(@PathVariable String jobId) {
        if (ObjectUtil.isNull(jobId)) {
            return AjaxResult.error(Enums.httpCode.ERROR_10.getValue());
        }
        Map<String, Object> resMap = new HashMap<>(5);
        Text2videoJob job = new Text2videoJob();
        job.setJobId(jobId);
        Text2videoJob jobResult = text2videoJobService.selectText2videoJobByJobId(job);
        String isSuccess=jobResult.getIsSuccess();
        switch (isSuccess) {
            case "1":
                resMap.put("isSuccess", true);
                resMap.put("message", Enums.httpCode.SUCCESS.getValue());
                resMap.put("percentage", 100);
                resMap.put("downloadUrl", jobResult.getBackup2());
                break;
            case "-1":
                resMap.put("isSuccess", false);
                resMap.put("message", Enums.JobSign.NLP_FAILED.getValue());
                resMap.put("percentage", 5);
                resMap.put("downloadUrl", jobResult.getBackup2());
                break;
            case "-2":
                resMap.put("isSuccess", false);
                resMap.put("message", Enums.JobSign.TTS_FAILED.getValue());
                resMap.put("percentage", 10);
                resMap.put("downloadUrl", jobResult.getBackup2());
                break;
            case "-3":
                resMap.put("isSuccess", false);
                resMap.put("message", Enums.JobSign.COM_FAILED.getValue());
                resMap.put("percentage", 60);
                resMap.put("downloadUrl", jobResult.getBackup2());
                break;
            case "-7":
                resMap.put("isSuccess", false);
                resMap.put("message", Enums.JobSign.RUN_NLP.getValue());
                resMap.put("percentage", 40);
                resMap.put("downloadUrl", jobResult.getBackup2());
                break;
            case "-10":
                resMap.put("isSuccess", false);
                resMap.put("message", Enums.JobSign.QUEUED_COM.getValue());
                resMap.put("percentage", 60);
                resMap.put("downloadUrl", jobResult.getBackup2());
                break;
            case "-11":
                resMap.put("isSuccess", false);
                resMap.put("message", Enums.JobSign.RUN_COM.getValue());
                resMap.put("percentage", 70);
                resMap.put("downloadUrl", jobResult.getBackup2());
                break;
        }
        return AjaxResult.success(resMap);
    }

    /**
     * 多任务查询接口
     *
     * @return
     */

    @GetMapping("/multiTaskProgress/{taskIds}")
    public AjaxResult multiTaskProgress1(@PathVariable String[] taskIds) {
        if (taskIds.length == 0) {
            return AjaxResult.error(Enums.httpCode.ERROR_10.getValue());
        }
        Map<String, String> mapRes = multiTaskProgress(taskIds);
        return AjaxResult.success(mapRes);
    }

    private Map<String, String> multiTaskProgress(String[] taskIds) {
        ArrayList<String> strings = ListUtil.toList(taskIds);
        Map<String, String> map = new HashMap();
        String info = "";
        List<Text2videoJob> jobs = text2videoJobService.selectText2videoJobById(strings);
        for (String taskId : taskIds) {
            String res = jobs.toString();
            if (!res.contains(taskId)) {
                map.put(taskId, Enums.httpCode.ERROR_16.getValue());
            }
        }
        for (Text2videoJob job : jobs) {
            String isSuccess = job.getIsSuccess();
            switch (isSuccess) {
                case "0":
                    info = "正在运行。标题：" + job.getTitle();
                    break;
                case "1":
                    info = "完成。标题：" + job.getTitle() + "。" + job.getBackup2();
                    break;
                case "-1":
                    info = "NLP服务失败。标题：" + job.getTitle() + "。失败原因:" + job.getBackup2();
                    break;
                case "-2":
                    info = "TTS服务失败。标题：" + job.getTitle() + "。失败原因" + job.getBackup2();
                    break;
                case "-3":
                    info = "合成服务失败。标题：" + job.getTitle() + "。失败原因" + job.getBackup2();
                    break;
                case "-4":
                    info = "文件校验失败。失败原因：" + job.getBackup2();
                    break;
                case "-5":
                    info = "线程池排队过多，正在等待提交任务" + job.getTitle();
                    break;
                default:
                    info = "没有提交任务。标题：" + job.getTitle();
            }
            map.put(job.getJobId(), info);
        }
        return map;
    }


    /**
     * 任务更新接口，根据taskID更新标题和文章，重新开始任务
     *
     * @param taskId
     * @return
     */
    @PostMapping("/retry")
    public AjaxResult retry(String taskId) {
        if (StrUtil.isEmpty(taskId)) {
            return AjaxResult.error(Enums.httpCode.ERROR_10.getValue());
        }
        try {
            // textPackageTaskService.retry(taskId);
        } catch (Exception e) {
            logger.error(Enums.httpCode.ERROR_17.getValue(), e);
            return AjaxResult.error(e.getMessage());
        }
        return AjaxResult.success();
    }

    @GetMapping("/download")
    public String downlaodFile(HttpServletResponse response
            , @RequestParam("zipId") String zipId
            , @RequestHeader("user-agent") String userAgent
            , @RequestParam(required = false, defaultValue = "false") boolean inline) throws IOException {

        List<Map<String, String>> list = iText2videoZipJobService.selectDownloadUrl(zipId);
        String res = JSON.toJSONString(list);
        String videoPathWithZip = taskVideoPath.replace("taskVideos", zipId);
        String txtFile = videoPathWithZip + File.separator + zipId + ".json";
        if (FileUtil.exist(txtFile)) {
            FileUtil.del(txtFile);
        }
        FileUtil.writeString(res, txtFile, Charset.defaultCharset());
        String taskVideoUrlZip = taskVideoUrl.replace("taskVideos", zipId);
        return taskVideoUrlZip;
    }

}
